import { ASTNode, PRECEDENCE, Token } from "./types";

export const parse = (tokens: Token[]): ASTNode => {
  let index = 0;

  const parseExpression = (minPrecedence = 0): ASTNode => {
    // eslint-disable-next-line @typescript-eslint/no-use-before-define
    let left = parsePrimary();

    c: while (index < tokens.length) {
      const token = tokens[index];
      if (token.type === ")" || PRECEDENCE[token.type] <= minPrecedence) break;
      // TODO:逗号处理
      if (token.type === ",") {
        // parsePrimary();

        break c;
      }
      // if (token.type === ',') {
      //   // //
      //   index += 2;
      //   left = { type: 'NUMARG', numArgs: Number(tokens[index - 1]?.value) };
      //   continue;
      //   // return tokens[index].value;
      // }
      const operator = token.type;
      index++;
      const right = parseExpression(PRECEDENCE[operator]) as ASTNode;
      left = { type: "BINARY", operator, left, right };
    }

    return left;
  };

  const parsePrimary = (): ASTNode => {
    const token = tokens[index++];
    if (token.type === "NUMBER") {
      return {
        type: "NUMBER",
        value: token.value,
      };
    } else if (token.type === "FUNCTION") {
      const args: ASTNode[] = [];
      let numArgs: any[] = [];
      if (tokens[index++].type !== "(") {
        throw new Error("Expected (");
      }
      while (tokens[index].type !== ")") {
        if (tokens[index].type === ",") {
          // 逗号处理
          index++;
          numArgs.push(parseExpression());
        } else {
          args.push(parseExpression());
        }
      }
      index++;
      return { type: "FUNCTION", numArgs, name: token.value, args };
    } else if (token.type === "(") {
      const expr = parseExpression();
      if (tokens[index++].type !== ")") {
        throw new Error("Expected )");
      }
      return expr;
    }

    throw new Error("Unexpected token");
  };

  return parseExpression();
};
